using System;
using Ext;
using Ext.data;
using Ext.grid;
using Ext.menu;
using ScriptFX;

namespace PageScripts {
    public class CategoriesDialog : Ext.util.Observable {
        private Grid _categoriesGrid;
        private Menu _contextMenu;
        private LayoutDialog _dialog;
        private CategoryDetailsForm _detailsForm;
        private Dictionary _buttons = new Dictionary();

        public CategoriesDialog() {
            _detailsForm = new CategoryDetailsForm();
            addEvents(new Dictionary(
                "categoryupdated", true,
                "categorydeleted", true
            ));
        }

        public void Show(Element el) {
            if (Script.IsNullOrUndefined(_dialog)) init();
            _dialog.show(el);
        }

        public Store GetCategoriesStore() {
            if (Script.IsNullOrUndefined(_dialog)) init();
            return _categoriesGrid.getDataSource();
        }

        private void init() {
            CreateGrid();
            CreateContextMenu();
            CreateToolbar();
            CreateDialog();
            CreateDetailsForm();

            _categoriesGrid.getDataSource().load(null);
        }

        private void CreateGrid() {
            ColumnModel cm = new ColumnModel(new Dictionary[] {
                          new Dictionary("header", "Name", "dataIndex", "CategoryName"),
                          new Dictionary("header", "Description", "dataIndex", "Description") 
                      });

            _categoriesGrid = new Grid("category-grid", new Dictionary(
                "ds", CreateStore("ListCategories"),
                "cm", cm,
                "selModel", new RowSelectionModel(new Dictionary("singleSelect", true)),
                "enableColLock", false,
                "autoSizeColumns", true,
                "autoExpandColumn", 1,
                "monitorWindowResize", true,
                "loadMask", true
            ));
            _categoriesGrid.on(GridEvents.contextmenu, new GridContextmenuDelegate(
                delegate(EventObject e) {
                    if ((bool)e.shiftKey) return;
                    e.stopEvent();
                    _contextMenu.showAt(e.getXY(), null);
                }),
                this,
                null
            );
            _categoriesGrid.on(GridEvents.rowdblclick, new GridRowdblclickDelegate(
                delegate(Grid grid, int rowIndex, EventObject e) {
                    EditSelectedCategory();
                }
            ), this, null);

            _categoriesGrid.render();
        }

        private Store CreateStore(string action) {
            if (Script.IsNullOrUndefined(action)) action = "ListCategories";

            return new Store(new Dictionary(
                "proxy", new HttpProxy(new Dictionary("url", "DataHandler.aspx")),
                "reader", new JsonReader(
                            new Dictionary(
                                "root", "results",
                                "totalProperty", "totalCount",
                                "id", "CategoryID"
                            ),
                            new string[] {"CategoryID", "CategoryName", "Description"}
                           ),
                "remoteSort", true,
                "baseParams", new Dictionary("action", action)
            ));
        }

        private void CreateContextMenu() {
            _contextMenu = new Menu(new Dictionary(
                "id", "mainMenu",
                "items", new object[] {
                    new Dictionary("icon", "js/ext-1.1/images/table_edit.png", "text", "Edit Category", "scope", this, "handler", new Callback(EditSelectedCategory)), 
                    new Dictionary("icon", "js/ext-1.1/images/table_delete.png", "text", "Delete Category", "scope", this, "handler", new Callback(DeleteSelectedCategory)), 
                    new Dictionary("icon", "js/ext-1.1/images/table_refresh.png", "text", "Refresh List", "scope", this, "handler", new Callback(RefreshList)), 
                    "-",
                    new Dictionary("icon", "js/ext-1.1/images/table_add.png", "text", "Add New Category", "scope", this, "handler", new Callback(AddNewCategory)), 
                }
            ));
        }

        private void CreateToolbar() {
            ToolbarClass tb = new ToolbarClass(_categoriesGrid.getView().getHeaderPanel(true), null, null);
            _buttons["add"] = tb.addButton(UIHelper.CreateButton("New", "Add New Category", "add", AddNewCategory, this));
            _buttons["edit"] = tb.addButton(UIHelper.CreateButton("Edit", "Edit the selected Category", "edit", EditSelectedCategory, this));
            _buttons["del"] = tb.addButton(UIHelper.CreateButton("Delete", "Delete the selected Category", "delete", DeleteSelectedCategory, this));
            _buttons["ref"] = tb.addButton(UIHelper.CreateButton("Refresh", "Refresh the list of Categories", "refresh", RefreshList, this));
            // add a greedy spacer
            Element.get(Element.get(tb.addSpacer().getEl()).dom.ParentNode).setStyle("width", "100%");
            _buttons["help"] = tb.addButton(UIHelper.CreateButton("Help", "Help on this page", "help", ShowHelp, this));
        }

        private void CreateDialog() {
            _dialog = new LayoutDialog("category-dialog", new Dictionary(
                "modal", false,
                "width", 400,
                "height", 400,
                "shadow", true,
                "minWidth", 300,
                "minHeight", 300,
                "proxyDrag", true,
                "center", new Dictionary("autoScroll", true)
            ));
            _dialog.addKeyListener(27, new AnonymousDelegate(delegate() { _dialog.hide(null); }), _dialog);
            _dialog.addButton("Close", new AnonymousDelegate(delegate() { _dialog.hide(null); }), _dialog);

            BorderLayout layout = _dialog.getLayout();
            layout.beginUpdate();
            layout.add("center", new GridPanel(_categoriesGrid, null));
            layout.endUpdate(false);
        }

        private void CreateDetailsForm() {
            _detailsForm = new CategoryDetailsForm();
            _detailsForm.on(CategoryDetailsFormEvents.inserted, new CategoryDetailsFormInsertedDelegate(
                delegate(CategoryDetailsForm form, bool success) {
                    if (success) _categoriesGrid.getDataSource().reload(null);
                }    
            ), this, null);
            _detailsForm.on(CategoryDetailsFormEvents.updated, new CategoryDetailsFormUpdatedDelegate(
                delegate(CategoryDetailsForm form, bool success, Dictionary values) {
                    if (success) {
                        _categoriesGrid.getDataSource().reload(null);
                        fireEvent(CategoriesDialogEvents.categoryupdated, values);
                    }
                }
            ), this, null);
        }

        private void AddNewCategory() {
            _contextMenu.hide(false);
            _detailsForm.Show(FormMode.Insert, ((Button)_buttons["add"]).getEl(), null);
        }

        private void EditSelectedCategory() {
            Record row = ((RowSelectionModel)_categoriesGrid.getSelectionModel()).getSelected();
            if (Script.IsNullOrUndefined(row)) {
                MessageBox.alert("Select a Category first ...", "Please choose a category to delete from the list.", null, null);
                return;
            }
            _contextMenu.hide(false);
            _detailsForm.Show(FormMode.Update, ((Button)_buttons["edit"]).getEl(), row);
        }

        private void DeleteSelectedCategory() {
            Record row = ((RowSelectionModel)_categoriesGrid.getSelectionModel()).getSelected();
            if (Script.IsNullOrUndefined(row)) {
                MessageBox.alert("Select a Category first ...", "Please choose a category to delete from the list.", null, null);
                return;
            }
            _contextMenu.hide(false);
            MessageBox.confirm("Really Delete?", "Are you sure you want to delete '" + row.get("CategoryName") + "'", new MessageBoxResponseDelegate(
                delegate(string button, string text) {
                    if (button != "yes") return;
                    Store ds = CreateStore("DeleteCategory");
                    ds.load(new Dictionary("params", new Dictionary("CategoryID", row.get("CategoryID"))));
                    _categoriesGrid.getDataSource().remove(row);
                    fireEvent(CategoriesDialogEvents.categorydeleted, row.get("CategoryID"));
                }), 
                this
            );
        }

        private void RefreshList() {
            _categoriesGrid.getDataSource().reload(null);
        }

        private void ShowHelp() {
            MessageBox.alert("Help", "<br /> Coming Soon ... <br />", null, null);
        }
    }

    public class CategoriesDialogEvents {
        /// <summary>Fires when a new category is inserted
        /// <pre><code>
        /// USAGE: function(Dictionary newValues)
        /// </code></pre>
        /// <list type="bullet">
        /// <item><term><b>newValues</b></term><description>object literal of the new category values</description></item>
        /// </list>
        /// </summary>
        public static string categoryupdated { get { return "categoryupdated"; } }
        /// <summary>Fires when a new category is deleted
        /// <pre><code>
        /// USAGE: function(int categoryId)
        /// </code></pre>
        /// <list type="bullet">
        /// <item><term><b>categoryId</b></term><description>the id of the deleted category</description></item>
        /// </list>
        /// </summary>
        public static string categorydeleted { get { return "categorydeleted"; } }

    }

    public delegate void CategoriesDialogUpdatedDelegate(Dictionary newValues);
    public delegate void CategoriesDialogDeletedDelegate(int categoryId);
}
